﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;
using System.Xml;

using DBServerCollection = MyLibrary.Data.DatabaseCollection.ServerConnectionCollection<System.String, System.Data.IDbConnection>;

namespace MyLibrary.Data.DatabaseCollection
{
    public class DatabaseCollection : IDisposable
    {
        #region 变量和属性
        private DBServerCollection _serverConnection = null;

        public DBServerCollection Connections
        {
            get { return _serverConnection; }
            set { _serverConnection = value; }
        }

        private string _configFile = String.Empty;
        /// <summary>
        /// 配置文件路径
        /// </summary>
        public string ConfigFile
        {
            get { return _configFile; }
            set { _configFile = value; }
        }

        private string _sectionName = "Connection";
        /// <summary>
        /// 配置文件节
        /// </summary>
        public string SectionName
        {
            get { return _sectionName; }
            set { _sectionName = value; }
        }

        private bool _isEncrypt = false;
        /// <summary>
        /// 连接字符串是否为加密
        /// </summary>
        public bool IsEncrypt
        {
            get { return _isEncrypt; }
            set { _isEncrypt = value; }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 默认构造函数,返回空DatabaseCollection集合
        /// </summary>
        public DatabaseCollection() : this(String.Empty, "Connection", false) { }

        /// <summary>
        /// 使用指定的配置文件,初始化DatabaseCollection
        /// </summary>
        /// <param name="configPath">配置文件路径</param>
        public DatabaseCollection(string configPath) : this(configPath, "Connection", false) { }

        /// <summary>
        /// 使用指定的配置文件节,初始化DatabaseCollection
        /// </summary>
        /// <param name="configPath"></param>
        /// <param name="section"></param>
        public DatabaseCollection(string configPath, string section) : this(configPath,section,false) { }

        /// <summary>
        /// 使用指定的配置文件节,初始化DatabaseCollection,可以指定是否为加密字符串
        /// </summary>
        /// <param name="configPath"></param>
        /// <param name="section"></param>
        /// <param name="isEncrypt"></param>
        public DatabaseCollection(string configPath, string section, bool isEncrypt)
        {
            _serverConnection = new DBServerCollection();
            this._configFile = configPath;
            this._sectionName = section;
            this._isEncrypt = isEncrypt;
        }

        public DatabaseCollection(string configPath, bool isEncrypt) : this(configPath, "Connection", isEncrypt) { }

        /// <summary>
        /// 使用指定的连接集合初始化DatabaseCollection
        /// </summary>
        /// <param name="connections"></param>
        public DatabaseCollection(List<IDbConnection> connections)
        {
            _serverConnection = new DBServerCollection();
            int count = 1;
            foreach (IDbConnection connection in connections)
                _serverConnection.AddConnection("Connection_" + count, connection);
        }

        ~DatabaseCollection()
        {
            dispose(false);
        }
        #endregion

        #region 方法
        /// <summary>
        /// 从配置文件中加载数据库连接
        /// </summary>
        /// <param name="section">配置节名</param>
        private void LoadConnectionFromConfigFile(string section)
        {
            if (String.IsNullOrEmpty(_configFile)) throw new ArgumentNullException("配置文件路径为空");
            if (!File.Exists(_configFile)) throw new FileNotFoundException("设置的配置文件路径不存在");
            if (_configFile.Substring(_configFile.LastIndexOf('.') + 1).ToLower() != "xml") throw new FileLoadException("配置文件必须是XML类型的文件");

            XmlDocument xDoc = new XmlDocument();
            try
            {
                xDoc.Load(_configFile);
            }
            catch
            {
                throw new XmlException("指定的文件不是有效的XML文件");
            }

            //查找配置节
            XmlNodeList connList = xDoc.SelectNodes("//" + section + "");
            if (connList.Count == 0) throw new ArgumentNullException("配置文件中不存在连接配置节,请检查配置文件中是否存在<" + section + ">的配置节");

            int subConnNum = 1;
            string connType = String.Empty;
            string connKey = String.Empty;

            try
            {
                IDbConnection tmpConnection = null;
                foreach (XmlNode node in connList)
                {
                    //读取配置节的属性
                    //节点不完整
                    if (node.Attributes["key"] == null || node.Attributes["type"] == null || node.Attributes["number"] == null) continue;
                    connType = node.Attributes["type"].Value;
                    //不支持数据类型
                    if (connType.ToLower() != "mssql" && connType.ToLower() != "mysql" && connType.ToLower() != "odbc") continue;
                    //加解密字符串的Key
                    connKey = node.Attributes["key"].Value + "@" + connType;
                    subConnNum = Convert.ToInt32(node.Attributes["number"].Value);
                    //连接数量不正确
                    if (subConnNum <= 0) continue;

                    string connectionString = String.Empty;
                    for (int i = 0; i < subConnNum; i++)
                    {
                        connectionString = this._isEncrypt ? Tools.CommonTools.Decrypt(node.InnerText, connKey) : node.InnerText;
                        //只建立一个连接
                        if (connType.ToLower() == "mssql")
                            tmpConnection = new System.Data.SqlClient.SqlConnection(connectionString);
                        else if (connType.ToLower() == "mysql")
                            tmpConnection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
                        else if (connType.ToLower() == "odbc")
                            tmpConnection = new System.Data.Odbc.OdbcConnection(connectionString);

                        if (subConnNum == 1)
                        {
                            _serverConnection.AddConnection(node.Attributes["key"].Value, tmpConnection);
                            _serverConnection.ConnetcionStringCollection.Add(node.Attributes["key"].Value, connectionString);
                            Console.WriteLine(node.Attributes["key"].Value + "成功!");
                        }
                        else
                        {
                            _serverConnection.AddConnection(node.Attributes["key"].Value + (i + 1).ToString(), tmpConnection);
                            _serverConnection.ConnetcionStringCollection.Add(node.Attributes["key"].Value + (i + 1).ToString(), connectionString);
                            Console.WriteLine(node.Attributes["key"].Value + (i + 1).ToString() + "成功!");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if(_serverConnection.Count != 0)
                    _serverConnection.RemoveAllConnection();
                throw ex;
            }
        }
        /// <summary>
        /// 从配置文件中加载数据库连接
        /// </summary>
        public void LoadConnectionFromConfigFile()
        {
            LoadConnectionFromConfigFile(this._sectionName);
        }
        #endregion

        #region IDisposable Members

        private void dispose(bool disposing)
        {
            if (disposing)
            {
                if (_serverConnection != null)
                {
                    _serverConnection.RemoveAllConnection();
                    _serverConnection = null;
                }
                GC.SuppressFinalize(this);
            }
        }

        public void Dispose()
        {
            dispose(true);
        }

        #endregion
    }
}

